<template>
  <div :style="field.formGroupStyle" v-if="!hidden"
       :class="[field.fields === undefined ? 'va-df-form-group' : 'va-df-complex-form-group', {[commonClasses.errorFieldClass]: error && error.rule}, field.formGroupClass]">
    <label-field></label-field>
    <div :style="field.inputWrapperStyle" :class="[field.fields === undefined ? 'va-df-input-wrapper' : 'va-df-complex-field-wrapper', field.inputWrapperClass]">
      <template v-if="field.fields === undefined">
        <div :class="[commonClasses.commonInputGroupClass, {'va-df-input-loading': isLoading}]" v-if="field.addon || field.addonHtml">
          <span :class="commonClasses.commonInputGroupAddonClass" v-if="field.addonOnLeft">
            <span v-if="field.addonHtml" v-html="field.addonHtml"></span>
            <template v-else>
              {{field.addon}}
            </template>
          </span>
          <input-field
               :index="index"
               :value="model[field.name]"
               :form-submitting="formSubmitting"
               @upload="onUpload"
               @validate="onValidate"
               @pending="onPending"
               @loading="onLoading"
               @field-destroyed="onFieldDestroyed"></input-field>
          <span :class="commonClasses.commonInputGroupAddonClass" v-if="!field.addonOnLeft">
            <span v-if="field.addonHtml" v-html="field.addonHtml"></span>
            <template v-else>
              {{field.addon}}
            </template>
          </span>
        </div>
        <input-field v-else :class="{'va-df-input-loading': isLoading}"
             :index="index"
             :value="model[field.name]"
             :field="field"
             :form-submitting="formSubmitting"
             @upload="onUpload"
             @validate="onValidate"
             @pending="onPending"
             @loading="onLoading"
             @field-destroyed="onFieldDestroyed"></input-field>
      </template>
      <template v-else>
        <template v-if="field.repeatable">
          <template v-for="(m, idx) in model[field.name]">
            <div :key="m.$index" class="va-df-repeat-item-wrapper" :style="field.repeatItemWrapperStyle" :class="field.repeatItemWrapperClass">
              <template v-for="subField in field.fields">
                <dynamic-form-form-group
                  :key="`${subField.name}${m.$index}`"
                  :index="index"
                  :field="subField"
                  :model="m"
                  :form-submitting="formSubmitting"
                  @upload="onUpload"
                  @loading="onLoading"
                  @validate="onValidate"
                  @pending="onPending"
                  @field-destroyed="onFieldDestroyed"></dynamic-form-form-group>
              </template>
              <div class="va-df-button-wrapper" :style="field.repeatActionsWrapperStyle" :class="field.repeatActionsWrapperClass" v-if="field.readonly !== true">
                <button type="button" :style="field.repeatActionButtonStyle" v-if="!field.repeatMoveUpDisabled" :class="[commonClasses.commonButtonClass, field.repeatActionButtonClass]"
                        :disabled="idx === 0" @click.prevent="repeatUp(m)">
                  {{lang('buttons.up')}}
                </button>
                <button type="button" :style="field.repeatActionButtonStyle" :class="[commonClasses.commonButtonClass, field.repeatActionButtonClass]"
                        :disabled="idx === model[field.name].length - 1" v-if="!field.repeatMoveDownDisabled" @click.prevent="repeatDown(m)">
                  {{lang('buttons.down')}}
                </button>
                <button type="button" :style="field.repeatActionButtonStyle" :class="[commonClasses.commonButtonClass, field.repeatActionButtonClass]"
                        :disabled="repeatMaxLength > 0 && idx > repeatMaxLength" v-if="!field.repeatAddDisabled" @click.prevent="repeatAdd(m)">
                  {{lang('buttons.add')}}
                </button>
                <button type="button" :style="field.repeatActionButtonStyle" :class="[commonClasses.commonButtonClass, field.repeatActionButtonClass]"
                        :disabled="idx < repeatMinLength" v-if="!field.repeatRemoveDisabled" @click.prevent="repeatRemove(m)">
                  {{lang('buttons.remove')}}
                </button>
              </div>
            </div>
          </template>
          <div class="va-df-button-wrapper" :style="field.repeatActionsWrapperStyle" v-if="!field.repeatAddDisabled" :class="[commonClasses.commonButtonClass, field.repeatActionsWrapperClass]">
            <button type="button" :style="field.repeatActionButtonStyle" :class="[commonClasses.commonButtonClass, field.repeatActionButtonClass]"
                    v-if="!model[field.name] || model[field.name].length === 0" @click.prevent="repeatAdd()">
              {{lang('buttons.add')}}
            </button>
          </div>
        </template>
        <template v-else>
          <template v-for="subField in field.fields">
            <dynamic-form-form-group
              :key="subField.name"
              :index="index"
              :field="subField"
              :model="model[field.name]"
              :form-submitting="formSubmitting"
              @upload="onUpload"
              @loading="onLoading"
              @validate="onValidate"
              @pending="onPending"
              @field-destroyed="onFieldDestroyed"></dynamic-form-form-group>
          </template>
        </template>
      </template>
      <error-message
        :error="error"></error-message>
      <p class="va-df-description" v-if="field.description" v-html="field.description"></p>
    </div>
  </div>
</template>

<script>
  import _ from 'lodash'
  import Vue from 'vue'
  import InputField from './InputField.vue'
  import LabelField from './LabelField.vue'
  import ErrorMessage from './ErrorMessage.vue'
  import LocaleMixin from '../locales/mixin'
  import Emitter from '../utils/emitter-mixin'

  let _objectModelKeyId = 0

  function getObjectModelKeyId () {
    return ++_objectModelKeyId
  }

  /*
  * 暂不支持slot的object及array
  * */
  export default {
    name: 'DynamicFormFormGroup',
    mixins: [LocaleMixin, Emitter],
    components: { LabelField, ErrorMessage, InputField },
    props: {
      index: Number,
      field: {
        type: Object,
        default () {
          return {}
        }
      },
      model: {
        type: Object,
        required: true
      },
      formSubmitting: {
        type: Boolean,
        default: false
      }
    },
    computed: {
      /*
      * 最近的具有model的组件（FormGroup或者DynamicForm）
      * */
      nmcComponent () {
        return this.findNMCParent()
      },
      form () {
        return this.getDynamicForm()
      },
      commonClasses () {
        return (this.form && this.form.formSchema && this.form.formSchema.commonClasses) || {}
      },
      formModel () {
        return (this.nmcComponent && this.nmcComponent.formModel) || {}
      },
      hidden () {
        if (_.isNil(this.field.hidden)) {
          return false
        }
        if (_.isFunction(this.field.hidden)) {
          return this.field.hidden(this.model, this.formModel, this.field)
        }
        return !!this.field.hidden
      },
      repeatMinLength () {
        if (_.isNil(this.field.repeatMinLength)) {
          return 0
        }
        if (_.isFunction(this.field.repeatMinLength)) {
          return this.field.repeatMinLength(this.model, this.formModel, this.field) || 0
        }
        return this.field.repeatMinLength || 0
      },
      repeatMaxLength () {
        if (_.isNil(this.field.repeatMaxLength)) {
          return null
        }
        if (_.isFunction(this.field.repeatMaxLength)) {
          return this.field.repeatMaxLength(this.model, this.formModel, this.field) || null
        }
        return this.field.repeatMaxLength || null
      },
      repeatDefaultModel () {
        if (_.isNil(this.field.repeatDefaultModel)) {
          return {}
        }
        if (_.isFunction(this.field.repeatDefaultModel)) {
          return this.field.repeatDefaultModel(this.model, this.formModel, this.field) || {}
        }
        return this.field.repeatDefaultModel || {}
      }
    },
    data () {
      return {
        isLoading: false,
        error: null,
        repeatErrors: {}
      }
    },
    created () {
      this.initModel()
    },
    watch: {
      model (newV, oldV) {
        if (newV !== oldV) {
          this.initModel()
        }
      }
    },
    methods: {
      initModel () {
        if (!this.model.__key) {
          this.model.__key = getObjectModelKeyId()
        }
        if (this.field.fields) {
          if (this.field.repeatable) {
            let fieldModel = this.model[this.field.name]
            if (!fieldModel || !_.isArray(fieldModel)) {
              Vue.set(this.model, this.field.name, [])
            }
            if (this.repeatMinLength > 0 && this.model[this.field.name].length < this.repeatMinLength) {
              while (this.model[this.field.name].length < this.repeatMinLength) {
                this.model[this.field.name].push(this.getNewRepeatModel())
              }
            }
          } else {
            if (!this.model[this.field.name]) {
              this.$set(this.model, this.field.name, {})
            }
            this.model[this.field.name].__key = getObjectModelKeyId()
          }
        }
      },
      getNewRepeatModel () {
        let obj = _.cloneDeep(this.repeatDefaultModel)
        obj.__key = getObjectModelKeyId()
        return obj
      },
      repeatUp (model) {
        let idx = _.indexOf(this.model[this.field.name], model)
        if (idx > 0) {
          this.model[this.field.name].splice(idx, 1)
          this.model[this.field.name].splice(idx - 1, 0, model)
        }
      },
      repeatDown (model) {
        let idx = _.indexOf(this.model[this.field.name], model)
        if (idx < this.model[this.field.name].length - 1) {
          this.model[this.field.name].splice(idx, 1)
          this.model[this.field.name].splice(idx + 1, 0, model)
        }
      },
      repeatAdd (model) {
        let idx = this.model[this.field.name].length
        if (model) {
          idx = _.indexOf(this.model[this.field.name], model) + 1
        }
        this.model[this.field.name].splice(idx, 0, this.getNewRepeatModel())
      },
      repeatRemove (model) {
        let idx = _.indexOf(this.model[this.field.name], model)
        this.model[this.field.name].splice(idx, 1)
      },
      onLoading (params) {
        this.isLoading = params.isLoading
        this.dispatch(['DynamicFormFormGroup', 'DynamicForm'], 'loading', params)
      },
      onUpload (params) {
        this.dispatch(['DynamicFormFormGroup', 'DynamicForm'], 'upload', params)
      },
      onValidate (params) {
        this.error = params
        this.dispatch(['DynamicFormFormGroup', 'DynamicForm'], 'validate', params)
      },
      onPending (params) {
        this.dispatch(['DynamicFormFormGroup', 'DynamicForm'], 'pending', params)
      },
      onFieldDestroyed (params) {
        this.dispatch(['DynamicFormFormGroup', 'DynamicForm'], 'field-destroyed', params)
      }
    }
  }
</script>
